package com.lnb.log.aspect;


import cn.hutool.core.date.SystemClock;
import cn.hutool.core.util.ArrayUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 记录请求以及处理信息
 *
 * @author 贺飞
 */
@Aspect
@Component
@Slf4j
public class LogAspect {

    private final ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    @Pointcut("execution(public * com.lnb.*.controller..*.*(..))")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void doBefore(JoinPoint joinPoint) {
        threadLocal.set(SystemClock.now());

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            HttpServletRequest request = requestAttributes.getRequest();
            String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
            Object[] paramValues = joinPoint.getArgs();

            log.info("开始http调用 => url: {}, 请求方式：{}, 参数:{}", request.getRequestURI(), request.getMethod(), logParam(paramNames,paramValues));

        }
    }

    @After("pointcut()")
    public void doAfterReturning(JoinPoint joinPoint) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            HttpServletRequest request = requestAttributes.getRequest();
            Long endTime = SystemClock.now();
            log.info("结束http调用 => url:{}, 耗时:{}ms", request.getRequestURI(), endTime - threadLocal.get());
        }
    }

    private String logParam(String[] paramsArgsName,Object[] paramsArgsValue){
        if(ArrayUtil.isEmpty(paramsArgsName) || ArrayUtil.isEmpty(paramsArgsValue)){
            return "";
        }
        StringBuilder buffer = new StringBuilder();
        for (int i=0;i<paramsArgsName.length;i++){
            //参数名
            String name = paramsArgsName[i];
            //参数值
            Object value = paramsArgsValue[i];
            buffer.append(name).append(" = ");
            if(null == value) {
                buffer.append("null" + ",");
            }else {
                if (isPrimite(value.getClass())) {
                    buffer.append(value).append("  ,");
                }else {
                    buffer.append(value).append("  ,");
                }
            }
        }
        return buffer.toString();
    }

    /**
     * 判断是否为基本类型：包括String
     * @param clazz clazz
     * @return  true：是;     false：不是
     */
    private boolean isPrimite(Class<?> clazz){
        if (clazz.isPrimitive() || clazz == String.class){
            return true;
        }else {
            return false;
        }
    }
}
